﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using ProtocoloPropietario;
using System.Threading;

namespace Servidor
{
    class Servidor
    {
        private IPAddress ipCliente;
        private int numPuertoCliente;
        private IPAddress ipServidor;
        private int numPuertoServidor;
        private int anchoBandaPorCliente;
        private AnchoDeBanda anchoDeBanda;

        public int AnchoBandaPorCliente
        {
            get { return anchoBandaPorCliente; }
            set { anchoBandaPorCliente = value; }
        }

        public IPAddress IpCliente
        {
            get { return ipCliente; }
            set { ipCliente = value; }
        }

        public int NumPuertoCliente
        {
            get { return numPuertoCliente; }
            set { numPuertoCliente = value; }
        }

        public IPAddress IpServidor
        {
            get { return ipServidor; }
            set { ipServidor = value; }
        }

        public int NumPuertoServidor
        {
            get { return numPuertoServidor; }
            set { numPuertoServidor = value; }
        }

        public AnchoDeBanda AnchoDeBanda
        {
            get { return anchoDeBanda; }
            set { anchoDeBanda = value; }
        }

        public Servidor(IPAddress ipServCliente, int puertoCliente, IPAddress ipServi, int puertoServidor, int anchoCliente, AnchoDeBanda ancho)
        {
            ipCliente = ipServCliente;
            numPuertoCliente = puertoCliente;
            anchoDeBanda = ancho;
            anchoBandaPorCliente = anchoCliente;
            numPuertoServidor = puertoServidor;
            ipServidor = ipServi;
        }

        public bool OtorgarAnchoDeBanda()
        {
            bool ok = true;
            int anchoDeBandaRestante = AnchoDeBanda.Total - AnchoDeBanda.Ocupado;
            if (anchoDeBandaRestante >= AnchoBandaPorCliente)
            {
                AnchoDeBanda.ActualizarAncho(AnchoBandaPorCliente);
                ThreadPool.QueueUserWorkItem(new WaitCallback(NotificarBandaAncha), null);
            }
            else
            {
                ok = false;
            }

            return ok;
        }

        public bool QuitarAnchoDeBanda()
        {
            bool ok = true;

            if (AnchoDeBanda.Ocupado > 0)
            {
                if (AnchoDeBanda.Ocupado < anchoBandaPorCliente)
                    AnchoDeBanda.Ocupado = 0;
                else
                    AnchoDeBanda.Ocupado = AnchoDeBanda.Ocupado - anchoBandaPorCliente;

                ThreadPool.QueueUserWorkItem(new WaitCallback(NotificarBandaAncha), null);
            }
            else
            {
                ok = false;
            }

            return ok;
        }

        private void NotificarBandaAncha(Object o)
        {
            string strMsj = ipServidor.ToString() + Protocolo.SEPARADOR + numPuertoServidor + Protocolo.SEPARADOR + IpCliente.ToString() + Protocolo.SEPARADOR + NumPuertoCliente + Protocolo.SEPARADOR + AnchoBandaPorCliente
                + Protocolo.SEPARADOR + AnchoDeBanda.Total + Protocolo.SEPARADOR + AnchoDeBanda.Ocupado;
            MensajeProtocolo msg = new MensajeProtocolo(Protocolo.Header.REQ, Protocolo.Comando.SERVIDOR_ACTUALIZAR_BANDA_ANCHA, strMsj.Length, strMsj);
            Program.conexion.EnviarPaqueteUDP(msg);
        }

        public override bool Equals(System.Object obj)
        {
            // If parameter is null return false.
            if (obj == null)
            {
                return false;
            }

            // If parameter cannot be cast to Point return false.
            Servidor s = obj as Servidor;
            if ((System.Object)s == null)
            {
                return false;
            }

            // Return true if the fields match:
            return (IpCliente.Equals(s.IpCliente)) && (NumPuertoCliente.Equals(s.NumPuertoCliente));
        }

        public bool Equals(Servidor s)
        {
            // If parameter is null return false:
            if ((object)s == null)
            {
                return false;
            }

            // Return true if the fields match:
            return (IpCliente.Equals(s.IpCliente)) && (NumPuertoCliente.Equals(s.NumPuertoCliente));
        }
    }
}
